package com.yonyou.pmclouds.signin.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.DateUtils;
import com.yonyou.pmclouds.outter.enterprise.EnterpriseInfoQuery;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.signin.entity.QueryListParam;
import com.yonyou.pmclouds.signin.entity.SignInListViewVO;
import com.yonyou.pmclouds.signin.rmiitf.SignInMaintain;
import com.yonyou.pmclouds.signin.rmiitf.SignInQuery;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseVO;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.rmiitf.TeamMemberQuery;
import com.yonyou.pmclouds.user.entity.UserInfo;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@RestController
@RequestMapping("/signin")
public class SignInController {
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private SignInQuery signInQuery;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private SignInMaintain maintain;

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private TeamMemberQuery teamMemberQuery;

    @Autowired
    private UserInfoQuery userQuery;
    @Autowired
    private EnterpriseInfoQuery enterpriseInfoQuery;

    /**
     * 获取区间内已签到的信息列表
     */
    @RequestMapping(value = "/getList")
    @ResponseBody
    public List<List<SignInListViewVO> > getList(@RequestBody QueryListParam queryListParam) throws BusinessException {
        if(queryListParam == null || StringUtils.isEmpty(queryListParam.getPkUser()) ||
                queryListParam.getStartDate() == null || queryListParam.getEndDate() == null){
            return null;
        }
        Map<String, List<List<SignInListViewVO>> > resultMap = signInQuery.getSignInListInfo(RuntimeEnvironment.getTenantId(),
                DateUtils.asDateBegin(queryListParam.getStartDate()), DateUtils.asDateEnd(queryListParam.getEndDate()), new String[]{queryListParam.getPkUser()});
        if(resultMap != null){
            return resultMap.get(queryListParam.getPkUser());
        }
        return null;
    }

    /**
     * 导出全员考勤表
     */
    @RequestMapping(value = "/exportList2Excel")
    public void exportList2Excel(HttpServletResponse response, @RequestParam("queryDate") Long queryDate,
                                 @RequestParam(value = "pageNum", required = false, defaultValue = "1") String pageNum,
                                 @RequestParam(value = "pageSize", required = false, defaultValue = "1000") String pageSize) throws IOException, BusinessException {

        response.setHeader("content-Type", "application/vnd.ms-excel");
        //下载文件的默认名称
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("考勤全员明细表","UTF-8") + ".xls");

        //获取用户信息数组
        UserInfo[] userInfos = userQuery.searchUsers(RuntimeEnvironment.getTenantId(), null, Integer.valueOf(pageNum), Integer.valueOf(pageSize)).getContent();
        if(ArrayUtils.isEmpty(userInfos)){
            return;
        }
        //用户主键数组
        String[] pkUsers = new String[userInfos.length];
        //关联<主键, 用户>
        Map<String, UserInfo> recordUser = new HashMap<>();

        for(int i = 0; i < userInfos.length; i++){
            if(userInfos[i] != null){
                pkUsers[i] = userInfos[i].getUserId();
                recordUser.put(userInfos[i].getUserId(), userInfos[i]);
            }
        }
        Map<String, UserInfo[]> recordEnterpriseUsers = new HashMap<>();
        //获取团队信息
        TeamMemberVO[] teamMemberVOS = getTeamMemberInfo(pkUsers, recordEnterpriseUsers, recordUser);

        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(queryDate);

        //构造要导出的Excel结构信息
        List<ExcelExportEntity> beanList = getExcelExportEntityList(cal);

        //构造要导出的Excel对应的DataSet
        List<Map<String, Object>> dataList = new ArrayList<>();
        if(ArrayUtils.isEmpty(teamMemberVOS)){
            return;
        }
        Map<String, String> enterpriseMap = new LinkedHashMap<>();
        for(TeamMemberVO teamMemberVO : teamMemberVOS){
            if(teamMemberVO != null && StringUtils.isNotEmpty(teamMemberVO.getPkEnterprise())){
                if(enterpriseMap.get(teamMemberVO.getPkEnterprise()) == null && teamMemberVO.getEnterpriseName() != null){
                    enterpriseMap.put(teamMemberVO.getPkEnterprise(), teamMemberVO.getEnterpriseName());
                }
            }
        }
        Map<String, List<List<SignInListViewVO>> > recordSignInList = getSignInListInfo(RuntimeEnvironment.getTenantId(), cal, pkUsers);

        int totNumber = 0;  //序号
        for(String pkEnterprise : enterpriseMap.keySet()){
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("enterpriseName", enterpriseMap.get(pkEnterprise));

            List<Map<String, Object>> numberNameList = new ArrayList<>();
            List<Map<String, Object>> dateList = new ArrayList<>();

            UserInfo[] currEnterpriseUsers = recordEnterpriseUsers.get(pkEnterprise);
            for(UserInfo userInfo : currEnterpriseUsers){
                Map<String, Object> numberNameMap = new HashMap<>();
                Map<String, Object> dateMap = new HashMap<>();

                numberNameMap.put("number", ++totNumber);
                numberNameMap.put("name", userInfo.getUserName());
                if(recordSignInList != null && recordSignInList.get(userInfo.getUserId()) != null) {
                    for(List<SignInListViewVO> list : recordSignInList.get(userInfo.getUserId())){
                        for(SignInListViewVO vo : list){
                            if(vo != null) {
                                cal.setTime(vo.getSigninTime());
                                break;
                            }
                        }
                        int day = cal.get(Calendar.DATE);
                        dateMap.put("date_" + day, getSignInMsg(list, cal));
                    }
                }
                numberNameList.add(numberNameMap);
                dateList.add(dateMap);
            }

            dataMap.put("numberAndName", numberNameList);
            dataMap.put("date", dateList);
            dataList.add(dataMap);
        }

        //导出
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("全员明细统计表", "考勤全员明细统计表"), beanList ,
                dataList);
        response.setCharacterEncoding("UTF-8");
        workbook.write(response.getOutputStream());
//        FileOutputStream fos = new FileOutputStream("C:/Users/Administrator/Desktop/t/ExcelExport.xls");
//        workbook.write(fos);
//        fos.close();
    }

    private String getSignInMsg(List<SignInListViewVO> list, Calendar cal){
        StringBuffer msg = new StringBuffer();
        if(list == null || list.size() == 0) return msg.toString();
        int count = 0;
        for(SignInListViewVO vo : list){
            if(vo == null) continue;
            cal.setTime(vo.getSigninTime());
            int hour = cal.get(Calendar.HOUR) + 12 * cal.get(Calendar.AM_PM);
            int minute = cal.get(Calendar.MINUTE);
            if(count > 0) msg.append("\n");
            msg.append(hour < 10 ? "0" + hour : "" + hour);
            msg.append(":");
            msg.append(minute < 10 ? "0" + minute : "" + minute);
            msg.append("  " + (vo.getPosition() == null ? "" : vo.getPosition()));
            count++;
        }
        return msg.toString();
    }
    private Map<String, List<List<SignInListViewVO>> > getSignInListInfo(String pkTenant, Calendar cal, String[] pkUsers) throws BusinessException {
        int countDay = cal.getActualMaximum(Calendar.DATE);
        cal.set(Calendar.DATE, 1);
        Date firstDay = cal.getTime();
        cal.set(Calendar.DATE, countDay);
        Date lastDay = cal.getTime();

        Map<String, List<List<SignInListViewVO>> > resultMap = signInQuery.getSignInListInfo(pkTenant,
                DateUtils.asDateBegin(firstDay), DateUtils.asDateEnd(lastDay), pkUsers);
        return resultMap;
    }

    private List<ExcelExportEntity> getExcelExportEntityList(Calendar cal){
        cal.set(Calendar.DATE, 1);
        String[] week = new String[]{"日", "一", "二", "三", "四", "五", "六"};
        int month = cal.get(Calendar.MONTH) + 1;
        String prefixDate = cal.get(Calendar.YEAR) + "-" + (month < 10 ?  ("0" + month) : ("" + month))  + "-";
        int countDay = cal.getActualMaximum(Calendar.DATE);
        int firstDayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;

        List<ExcelExportEntity> beanList = new ArrayList<>();
        //企业名称
        ExcelExportEntity entity = new ExcelExportEntity("企业名称", "enterpriseName");
        entity.setWidth(40);
        entity.setWrap(true);
        entity.setNeedMerge(true);
        beanList .add(entity);
        //序号姓名组
        ExcelExportEntity numberNameGroup = new ExcelExportEntity("人员信息", "numberAndName");
        List<ExcelExportEntity> numberNameColList = new ArrayList<>();
        ExcelExportEntity numberEntity = new ExcelExportEntity("序号", "number");
        ExcelExportEntity nameEntity = new ExcelExportEntity("姓名", "name");
        nameEntity.setWidth(15);
        numberNameColList.add(numberEntity);
        numberNameColList.add(nameEntity);
        numberNameGroup.setList(numberNameColList);
        beanList.add(numberNameGroup);
        //日期组
        ExcelExportEntity dateGroup = new ExcelExportEntity("日期 " + "[" + prefixDate + "01, " + prefixDate + (countDay < 10 ?  ("0" + countDay) : ("" + countDay)) + "]", "date");
        List<ExcelExportEntity> dateColList = new ArrayList<>();
        for(int i = 1; i <= countDay; i++){
            ExcelExportEntity dateEntity = new ExcelExportEntity(i + "日" + "\n" + "星期" + week[(firstDayOfWeek++ % 7)], "date_" + i);
            dateEntity.setWidth(30);
            dateEntity.setWrap(true);
            dateColList.add(dateEntity);
        }
        dateGroup.setList(dateColList);
        beanList.add(dateGroup);

        return beanList;
    }

    private TeamMemberVO[] getTeamMemberInfo(String[] pkUsers, Map<String, UserInfo[] > recordEnterpriseUsers, Map<String, UserInfo> recordUser) throws BusinessException {
        TeamMemberVO[] teamMemberVOS = teamMemberQuery.queryByPkUsers(pkUsers);
        if(ArrayUtils.isNotEmpty(teamMemberVOS)){
            //企业信息添加
            enterpriseInfoQuery.tranEntInfoField(teamMemberVOS, new String[]{TeamMemberVO.PK_ENTERPRISE}, new String[]{TeamMemberVO.ENTERPRISE_NAME});
            Arrays.sort(teamMemberVOS, new Comparator<TeamMemberVO>() {
                @Override
                public int compare(TeamMemberVO o1, TeamMemberVO o2) {
                    if (o1 == o2) {
                        return 0;
                    }
                    if (o1 == null) {
                        return 1;
                    }
                    if (o2 == null) {
                        return -1;
                    }
                    if (!o1.getUserRole().equals(o2.getUserRole())) {
                        return o1.getUserRole().compareTo(o2.getUserRole());
                    }
                    int com = ChineseStringUtils.compareInDict(o1.getEnterpriseName(), o2.getEnterpriseName());
                    if (com != 0) {
                        return com;
                    }
                    return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());
                }
            });
            Map<String, Set<UserInfo> > enterpriseUsersSet = new HashMap<>();  //用户去重
            for(TeamMemberVO teamMemberVO : teamMemberVOS){
                if(teamMemberVO != null && StringUtils.isNotEmpty(teamMemberVO.getPkEnterprise())){
                    if(enterpriseUsersSet.get(teamMemberVO.getPkEnterprise()) == null){
                        enterpriseUsersSet.put(teamMemberVO.getPkEnterprise(), new HashSet<UserInfo>());
                    }
                    enterpriseUsersSet.get(teamMemberVO.getPkEnterprise()).add(recordUser.get(teamMemberVO.getPkUser()));
                    if(teamMemberVO.getUserRole() != null && teamMemberVO.getUserRole() > 10){
                        String role = teamMemberVO.getUserRole() == TeamEnterpriseVO.EnterpriseRoleConst.ROLE_CONSTRUCTOR ? "施工方" : "监理方";
                        teamMemberVO.setEnterpriseName(role + "--" + (teamMemberVO.getEnterpriseName() == null ? "" : teamMemberVO.getEnterpriseName()));
                    }
                }
            }

            for(String key : enterpriseUsersSet.keySet()){
                recordEnterpriseUsers.put(key, enterpriseUsersSet.get(key).toArray(new UserInfo[0]));
                Arrays.sort(recordEnterpriseUsers.get(key), new Comparator<UserInfo>() {
                    @Override
                    public int compare(UserInfo o1, UserInfo o2) {
                        if (o1 == o2) {
                            return 0;
                        }
                        if (o1 == null) {
                            return 1;
                        }
                        if (o2 == null) {
                            return -1;
                        }
                        return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());
                    }
                });
            }
        }
        return teamMemberVOS;
    }

}
